const fs = require('fs');
const path = require("path");
const DateTime = require('./datetime');

const LogLevel = Object.freeze({
	LOG_NULL: 0,
	LOG_TRACE: 1,//追踪
	LOG_DEBUG: 2,//调试
	LOG_INFO: 4,//一般信息
	LOG_WARN: 8,//警告
	LOG_ERROR: 16,//错误
	LOG_FATAL: 32,//严重错误
	LOG_FILE_ONLY: 32768//只写入文件
})

// function getStackTrace() {
//     let obj = {};
//     Error.captureStackTrace(obj, getStackTrace);
//     return obj.stack;
// }

class Log {
    constructor(dirname="./log/"){
        this.dirname = dirname;
        this.flieType = 0;//0按天，1按小时
        this._mkdirs(dirname);
        this.printLevel = 63;//打印默认级别
	    this.fileLevel = 60;//写文件默认级别
    }
    setType(type){
        this.flieType = type;
    }
    _mkdirs(dirname) {
        if (fs.existsSync(dirname)) {
            return true;
        } else {
            if (this._mkdirs(path.dirname(dirname))) {
                fs.mkdirSync(dirname);
                return true;
            }
        }
        return false;
    }
    _openfile() {
        let now = new DateTime();
        let fileName = "??";
        if (this.flieType==0) {
            fileName = now.date()+".log";
        } else {
            fileName = now.dateHour()+".log";
        }
        return [fileName, now.time()];
    }
    static _logLevel(logLevel) {
        switch (logLevel)
        {
        case 'TRACE':
        case LogLevel.LOG_TRACE:
            return ["[TRACE]", LogLevel.LOG_TRACE];
        case 'DEBUG':
        case LogLevel.LOG_DEBUG:
            return ["[DEBUG]", LogLevel.LOG_DEBUG];
        case 'INFO':
        case LogLevel.LOG_INFO:
            return ["[INFO]", LogLevel.LOG_INFO];
        case 'WARN':
        case LogLevel.LOG_WARN:
            return ["[WARN]", LogLevel.LOG_WARN];
        case 'ERROR':
        case LogLevel.LOG_ERROR:
            return ["[ERROR]", LogLevel.LOG_ERROR];
        case 'FATAL':
        case LogLevel.LOG_FATAL:
            return ["[FATAL]", LogLevel.LOG_FATAL];
        case 'FILE':
        case LogLevel.LOG_FILE_ONLY:
            return ["[FILE]", LogLevel.LOG_FILE_ONLY];
        default:
            return ["[?]", LogLevel.LOG_DEBUG];
        }
    }
    static _toString(str) {
        if (typeof str == 'object') {
            if (str instanceof Error) {
                if (str.stack!=undefined) {
                    return str.stack;
                } else {
                    return str.message;
                }
            } else {
                return JSON.stringify(str);
            }
        } else {
            return str;
        }
    }
    _logText(logLevel, str) { 
    }
    output(logLevel, str) {
        //文件名和时间
        const name = this._openfile();
        //类型
        const lv = Log._logLevel(logLevel);
        const head = `[${name[1]}]${lv[0]}`;
        const text = head+Log._toString(str);
        //打印
        if ((this.printLevel&lv[1]) && !(lv[1]&LogLevel.LOG_FILE_ONLY))
        {
            switch (lv[1]) {
                case LogLevel.LOG_TRACE:
                    console.trace(text);
                    break;
                case LogLevel.LOG_DEBUG:
                    console.debug(text);
                    break;
                case LogLevel.LOG_INFO:
                    console.info(text);
                    break;
                case LogLevel.LOG_WARN:
                    console.warn(text);
                    break;
                case LogLevel.LOG_ERROR:
                case LogLevel.LOG_FATAL:
                    console.error(text);
                    break;
                default:
                    console.log(text);
                    break;
            }
        }
        if ((this.fileLevel&lv[1]) || (lv[1]&LogLevel.LOG_FILE_ONLY))
        {
            fs.writeFile(this.dirname+name[0], text+"\r\n", {flag:"a+"}, function(){});
        }
    }
    debug(str) {
        this.output(LogLevel.LOG_DEBUG, str);
    }
    print(str) {
        this.output(LogLevel.LOG_INFO, str);
    }
    file(str) {
        this.output(LogLevel.LOG_FILE_ONLY, str);
    }
    error(str) {
        this.output(LogLevel.LOG_ERROR, str);
    }
    errorFile(str) {
        const txt = Log._toString(str);
        this.output(LogLevel.LOG_FILE_ONLY, '[ERROR]'+txt);
    }
}
Log.LogLevel = LogLevel;

// let logtest = new Log();
// logtest.print("print 1");
// logtest.file("print 2");
// logtest.error("print 3");
// logtest.errorFile("print 4");
// logtest.debug("print 5");
// try {
//     new Array(-1)
// } catch (error) {
//     logtest.error(error);
// }

module.exports = Log;